﻿using Sgr.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Sgr.Licence
{
    /// <summary>
    /// 许可证辅助工具类
    /// </summary>
    public static class LicenseHelper
    {
        #region 时间相关方法

        /// <summary>
        /// 转换为时间戳
        /// </summary>
        public static string ConvertToTimestamp(DateTime time)
        {
            var utc = time.EnsureUtc();

            var ticks = utc.Ticks - LicenseConstants.BenchmarkDate.Ticks;

            if (ticks <= 0)
                return "0";

            return ticks.ToString()[..^LicenseConstants.TimestampPrecision];
        }

        /// <summary>
        /// 从时间戳解析日期时间
        /// </summary>
        public static DateTime ParseDateTime(string timestamp)
        {
            if (string.IsNullOrWhiteSpace(timestamp))
                return Constant.MaxDateTime;

            if (!long.TryParse(timestamp, out var ticks) || ticks <= 0)
                return Constant.MaxDateTime;

            return LicenseConstants.BenchmarkDate.AddTicks(long.Parse(timestamp + "0000"));
        }

        #endregion 时间相关方法

        #region 激活码处理方法

        /// <summary>
        /// 计算校验和
        /// </summary>
        public static string CalculateChecksum(string input)
        {
            string hash = HashHelper.CreateSha256(input);
            return hash[..LicenseConstants.ChecksumLength];
        }

        /// <summary>
        /// 添加校验和
        /// </summary>
        public static string AppendChecksum(string input)
        {
            var checksum = CalculateChecksum(input);
            return $"{input}{checksum}";
        }

        /// <summary>
        /// 验证校验和
        /// </summary>
        public static bool VerifyChecksum(string input)
        {
            if (input.Length <= LicenseConstants.ChecksumLength)
                return false;

            var actualCode = input[..^LicenseConstants.ChecksumLength];
            var providedChecksum = input[^LicenseConstants.ChecksumLength..];
            var calculatedChecksum = CalculateChecksum(actualCode);

            return string.Equals(providedChecksum, calculatedChecksum, StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// 移除校验和
        /// </summary>
        public static string RemoveChecksum(string input) =>
            input[..^LicenseConstants.ChecksumLength];

        /// <summary>
        /// 安全解析长整型数值
        /// </summary>
        /// <param name="value">要解析的字符串</param>
        /// <returns>解析结果，解析失败返回0</returns>
        public static long ParseLongWithDefault(string value) =>
            long.TryParse(value, out var result) && result > 0 ? result : 0;

        /// <summary>
        /// 验证激活信息
        /// </summary>
        /// <param name="info">激活信息</param>
        /// <param name="registrationCode">注册码</param>
        /// <returns>验证结果，包含验证状态、消息和激活信息</returns>
        public static (bool IsValid, string Message, ActivationInfo? Info) ValidateActivationInfo(
            ActivationInfo info,
            string registrationCode)
        {
            if (info.RegistrationCode != registrationCode)
                return (false, "注册码不匹配", null);

            if (info.StartTime == Constant.MaxDateTime || info.EndTime == Constant.MinDateTime)
                return (false, "激活码包含无效的时间信息", null);

            if (info.NumOfLic <= 0)
                return (false, "无效的授权数量", null);

            return (true, "激活码有效", info);
        }

        /// <summary>
        /// 解析激活码
        /// </summary>
        public static ActivationInfo? ParseActivationCode(string activationCode)
        {
            if (string.IsNullOrEmpty(activationCode))
                return null;

            try
            {
                string decrypted;

                // 检查是否包含校验和
                if (activationCode.Length > LicenseConstants.ChecksumLength &&
                    VerifyChecksum(activationCode))
                {
                    var actualCode = RemoveChecksum(activationCode);
                    decrypted = EncryptionHelper.Decrypt(actualCode, false);
                }
                else
                {
                    // 兼容旧格式的激活码，不包含校验和
                    decrypted = EncryptionHelper.Decrypt(activationCode, false);
                }

                var parts = decrypted.Split(LicenseConstants.FieldSeparator);

                if (parts.Length < LicenseConstants.FieldCount || parts.Any(string.IsNullOrEmpty))
                    return null;

                var info = new ActivationInfo
                {
                    RegistrationCode = parts[0],
                    NumOfLic = ParseLongWithDefault(parts[1]),
                    StartTime = ParseDateTime(parts[3]),
                    EndTime = ParseDateTime(parts[4])
                };

                // 基本有效性验证
                if (info.EndTime <= info.StartTime)
                    return null;

                return info;
            }
            catch
            {
                return null;
            }
        }

        #endregion 激活码处理方法

        #region 注册码生成方法

        /// <summary>
        /// 生成注册码
        /// </summary>
        /// <returns>格式化的注册码</returns>
        public static string GenerateRegistrationCode()
        {
            var hardwareId = BuildHardwareIdentifier();
            var hash = HashHelper.CreateMd5(hardwareId);
            var paddedHash = hash.PadRight(25, 'A');

            return FormatRegistrationCode(paddedHash);
        }

        /// <summary>
        /// 构建硬件标识符
        /// </summary>
        /// <returns>包含计算机名和所有MAC地址的字符串</returns>
        public static string BuildHardwareIdentifier()
        {
            var sb = new StringBuilder();

            // 1. 使用机器名（基本信息，通常稳定且容易获取）
            sb.Append(Environment.MachineName);

            // 2. 获取物理网卡MAC地址
            foreach (var mac in HardwareEnvHelper.GetHostServerMacs())
            {
                sb.Append('#').Append(mac);
            }

            // 3. 获取操作系统信息（补充信息）
            sb.Append('#')
                .Append(Environment.OSVersion.Platform)
                .Append('#')
                .Append(Environment.ProcessorCount);

            return sb.ToString();
        }

        /// <summary>
        /// 格式化注册码
        /// </summary>
        /// <param name="input">输入字符串</param>
        /// <returns>按指定格式分组的注册码</returns>
        public static string FormatRegistrationCode(string input)
        {
            var result = new StringBuilder(30);
            for (int i = 0; i < 5; i++)
            {
                if (i > 0) result.Append(LicenseConstants.RegistrationCodeSeparator);
                result.Append(input.AsSpan(i * LicenseConstants.RegistrationCodeSegmentLength,
                    LicenseConstants.RegistrationCodeSegmentLength));
            }
            return result.ToString();
        }

        #endregion 注册码生成方法

        #region 文件操作方法

        /// <summary>
        /// 读取许可证文件内容
        /// </summary>
        /// <returns>许可证文件内容，文件不存在则返回null</returns>
        public static string? ReadLicenseFile()
        {
            try
            {
                var path = Path.Combine(LocalFileHelper.GetApplicationDirectory(),
                    LicenseConstants.LicenseFileName);
                return File.Exists(path) ? File.ReadAllText(path).Trim() : null;
            }
            catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)
            {
                // 可以添加日志记录
                return null;
            }
        }

        /// <summary>
        /// 保存许可证文件
        /// </summary>
        /// <param name="content">许可证内容</param>
        public static void SaveLicenseFile(string content)
        {
            var path = Path.Combine(LocalFileHelper.GetApplicationDirectory(),
                LicenseConstants.LicenseFileName);
            File.WriteAllText(path, content);
        }

        #endregion 文件操作方法
    }
}